package suites.tree {
	import org.flexunit.asserts.assertEquals;
	import org.flexunit.asserts.assertFalse;
	import org.flexunit.asserts.assertNull;
	import org.flexunit.asserts.assertTrue;
	import org.splink.library.tree.INode;
	import org.splink.library.tree.Node;
	import org.splink.library.tree.Tree;
	import org.splink.library.utils.ArrayUtils;

	/**
	 * @author maxmc
	 */
	public class TreeTest {
		private var _tree : Tree;

		[Before]
		public function before() : void {
			var xml : XML = <t>
								<n id='1'>
									<n id='4'/>
									<n id='5'>
										<n id='7' />
									</n>
								</n>
								<n id='2'>
									<n id='6'>
										<n id='8'/>
										<n id='9'/>
										<n id='10'/>
									</n>
								</n>
								<n id='3'/>
							</t>;
							
			_tree = Tree.fromXml(new Tree(null), xml, Node);
		}

		[After]
		public function after() : void {
			_tree.finalize();
			_tree = null;
		}
		
		[Test(description="visitor")]
		public function testVisit() : void {
			var a : Array = _tree.toArray();
			Tree.visit(_tree.root, function(n : INode) : void {
				assertTrue(ArrayUtils.contains(a, n));
				ArrayUtils.remove(a, n);
			});
			
			// the first arg node of the visit method is not visited, in our test this is the root node
			assertEquals(a.length, 1); 
		}

		[Test(description="clone tree")]
		public function testClone() : void {
			var t2 : Tree = new Tree(Tree.clone(_tree.root));
			
			assertFalse(ArrayUtils.eq(_tree.toArray(), t2.toArray()));
			assertTrue(_tree.toArray().toString() == t2.toArray().toString());
		}

		[Test(description="common parent")]
		public function testCommonParent() : void {
			assertEquals(commonParent("4", "5").id, "1");			assertEquals(commonParent("4", "6").id, _tree.root.id);			assertEquals(commonParent("3", "1").id, _tree.root.id);			assertEquals(commonParent("7", "5").id, "1");
		}
		
		[Test(description="first leaf")]
		public function testFirstLeaf() : void {		
			assertEquals(Tree.getNodeById("4", _tree.root), Tree.getFirstLeaf(_tree.root));
			assertEquals(Tree.getNodeById("4", _tree.root), Tree.getFirstLeaf(Tree.getNodeById("1", _tree.root)));
			assertEquals(Tree.getNodeById("8", _tree.root), Tree.getFirstLeaf(Tree.getNodeById("2", _tree.root)));
			assertEquals(Tree.getNodeById("3", _tree.root), Tree.getFirstLeaf(Tree.getNodeById("3", _tree.root)));
			assertEquals(Tree.getNodeById("8", _tree.root), Tree.getFirstLeaf(Tree.getNodeById("6", _tree.root)));			
		}
		
		[Test(description="last leaf")]
		public function testLastLeaf() : void {
			assertEquals(Tree.getNodeById("3", _tree.root), Tree.getLastLeaf(_tree.root));
			assertEquals(Tree.getNodeById("7", _tree.root), Tree.getLastLeaf(Tree.getNodeById("1", _tree.root)));
			assertEquals(Tree.getNodeById("10", _tree.root), Tree.getLastLeaf(Tree.getNodeById("2", _tree.root)));
			assertEquals(Tree.getNodeById("3", _tree.root), Tree.getLastLeaf(Tree.getNodeById("3", _tree.root)));
			assertEquals(Tree.getNodeById("10", _tree.root), Tree.getLastLeaf(Tree.getNodeById("6", _tree.root)));				
		}		
		
		[Test(description="previous leaf")]
		public function testPreviousLeaf() : void {
			assertNull(Tree.getPreviousLeaf(_tree.root));
			assertNull(Tree.getPreviousLeaf(Tree.getNodeById("4", _tree.root)));			
			assertEquals(Tree.getNodeById("9", _tree.root), Tree.getPreviousLeaf(Tree.getNodeById("10", _tree.root)));
			assertEquals(Tree.getNodeById("7", _tree.root), Tree.getPreviousLeaf(Tree.getNodeById("8", _tree.root)));			
			assertEquals(Tree.getNodeById("10", _tree.root), Tree.getPreviousLeaf(Tree.getNodeById("3", _tree.root)));				
		}
		
		[Test(description="next leaf")]
		public function testNextLeaf() : void {
			assertNull(Tree.getNextLeaf(_tree.root));			assertNull(Tree.getNextLeaf(Tree.getNodeById("3", _tree.root)));			
			assertEquals(Tree.getNodeById("8", _tree.root), Tree.getNextLeaf(Tree.getNodeById("7", _tree.root)));
			assertEquals(Tree.getNodeById("9", _tree.root), Tree.getNextLeaf(Tree.getNodeById("8", _tree.root)));
			assertEquals(Tree.getNodeById("3", _tree.root), Tree.getNextLeaf(Tree.getNodeById("10", _tree.root)));				
		}

		[Test(description="node index")]
		public function testNodeIndex() : void {
			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("1", _tree.root)), 1);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("2", _tree.root)), 5);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("3", _tree.root)), 10);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("4", _tree.root)), 2);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("5", _tree.root)), 3);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("6", _tree.root)), 6);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("7", _tree.root)), 4);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("8", _tree.root)), 7);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("9", _tree.root)), 8);			assertEquals(Tree.getNodeIndex(_tree.root, Tree.getNodeById("10", _tree.root)), 9);
		}

		private function commonParent(id1 : String, id2 : String) : INode {
			var n1 : INode = Tree.getNodeById(id1, _tree.root);			var n2 : INode = Tree.getNodeById(id2, _tree.root);
			return Tree.getCommonParent(n1, n2);
		}
	}
}
